#include "mychild.h"

MyChild::MyChild(QWidget *parent)
     : QTextEdit(parent)
{

    setAttribute(Qt::WA_DeleteOnClose);//关闭窗口时销毁
    isUntitle=true;//刚创建文档，标题没有更改需要另存为
}

void MyChild::newFile()//新建文件：给文本框对象设置标题
{
    static int sequenceNumber=1;//标识新建了多少个文件，函数内静态变量
    isUntitle=true;//表示文件没有重命名
    curFile=tr("Word文档=%1").arg(sequenceNumber++);//以这种样式命名
    setWindowTitle(curFile);//表明这个文本框的标题

}

bool MyChild::loadFile(const QString &fileName)
{
    if(!fileName.isEmpty())
    {
        if(!QFile::exists(fileName))
        {   qDebug()<<"文件不存在";
            return false;
        }
        QFile file(fileName);
        if(!file.open(QIODevice::ReadWrite))//打开文件方法，需要打开才能读取，用open打开
        {
            qDebug() << "打开失败:" << file.errorString();
            return false;
        }
        QByteArray data=file.readAll();
        file.close();
        QString str;
         // Qt6 替代方案：使用 QStringDecoder 自动检测编码
        QStringDecoder decoder(QStringDecoder::Utf8);
        str=decoder.decode(data);
        qDebug()<<str;
        // 如果 UTF-8 解码失败或可能不是纯文本，尝试系统本地编码
        if (decoder.hasError() || !decoder.isValid()) {
            QStringDecoder localDecoder(QStringDecoder::System);
            str = localDecoder.decode(data);
        }
        //检查是否为富文本
        if(Qt::mightBeRichText(str))
        {
            this->setHtml(str);//富文本方式放入文本框
        }
        else
        {
            this->setPlainText(str);//纯文本方式存放
        }
        setCurrentFile(fileName);//对打开的文件进行处理
        connect(document(),SIGNAL(contentsChange()),this,SLOT(documentWasModified()));
        //文本发生改变，就调用改变文本的函数
        return true;}
    return false;
}

bool MyChild::save()
{
    if(isUntitle)//文档标题没有更改就另存为，更改了就保存
    {
        return saveAs();
    }
    else
    {
        return saveFile(curFile);
    }
}

bool MyChild::saveAs()
{
    QString fileName=QFileDialog::getSaveFileName(this,tr("另存为"),curFile,tr("HTML,文档（*.html *.html);;所有文件(*.*)"));
    if(fileName.isEmpty())
    {
        return false;

    }

    return saveFile(fileName);//保存文件
}

bool MyChild::saveFile(QString fileName)
{
    if(!fileName.endsWith(".htm",Qt::CaseInsensitive)|fileName.endsWith(".html",Qt::CaseInsensitive))
    {
        fileName+=".html";
    }
    QTextDocumentWriter writer(fileName);//高级保存内容的方法
    bool success=writer.write(this->document());//将内容保存到文件中
    if(success)
        setCurrentFile(fileName);//保存文档到文件后更新状态，并且更改标题，这样下次就不会另存为了
    return success;
}


//字体格式设置
void MyChild::mergeFormationOnWordOrSelection(const QTextCharFormat &format)
{
    QTextCursor cursor = this->textCursor();
    if (!cursor.hasSelection())
    {cursor.select(QTextCursor::WordUnderCursor);
        if (!cursor.selectedText().isEmpty()) {
            cursor.mergeCharFormat(format);
        }
        else
        {  cursor.mergeCharFormat(format);
        }
        this->mergeCurrentCharFormat(format);// 设置当前字符格式（影响新输入的文本）

        // 确保光标回到正确位置
        this->setTextCursor(cursor);
    }
}

void MyChild::setAlign(int align)
{
    //设置段落对齐设置
    if(align==1)
        this->setAlignment(Qt::AlignLeft|Qt::AlignAbsolute);
    else if(align==2)
        this->setAlignment(Qt::AlignHCenter);// 水平方向居中。
    else if(align==3)
        this->setAlignment(Qt::AlignRight|Qt::AlignAbsolute);
    else if(align==4)
        this->setAlignment(Qt::AlignJustify);// 水平方向调整间距两端对齐。
}

void MyChild::setStyle(int style)
{
    QTextCursor cursor=this->textCursor();
    if(style!=0)
    {QTextListFormat::Style stylename;
    switch(style)
        {

        case 1:
            stylename = QTextListFormat::ListDisc; // # 样式为圆圈
            break;
        case 2:
            stylename = QTextListFormat::ListCircle; // # 样式为空心圆圈
            break;
        case 3:
            stylename = QTextListFormat::ListSquare;// 样式为方块
            break;
        case 4:
            stylename = QTextListFormat::ListDecimal; // 小写阿拉伯数字，最大4999
            break;
        case 5:
            stylename = QTextListFormat::ListLowerAlpha; // 小写拉丁字符，按字母顺序
            break;
        case 6:
            stylename = QTextListFormat::ListUpperAlpha; // 大写拉丁字符，按字母顺序
            break;
        case 7:
            stylename = QTextListFormat::ListLowerRoman; // 小写罗马数字，最大4999
            break;
        case 8:
            stylename = QTextListFormat::ListUpperRoman; // 大写罗马数字，最大4999
            break;
         default:stylename=QTextListFormat::ListDisc;break;//默认设置为圆圈
         }
        cursor.beginEditBlock();//开始对选中的内容进行设置格式,编辑块
         QTextBlockFormat blockfmt=cursor.blockFormat();//获取当前选中数据的原本格式
        QTextListFormat listfmt;//列表样式
         if(cursor.currentList())//如果当前块存在列表样式
        {
            listfmt=cursor.currentList()->format();//将已有的列表格式提取出来
         }
         else{
             //没有设置具有列表格式的文本格式
             //需要重新设置
             listfmt.setIndent(blockfmt.indent()+1);//列表缩进级别+1
             blockfmt.setIndent(0);//对文本缩进级别清空，遵循列表缩进级别
             cursor.setBlockFormat(blockfmt);}
         listfmt.setStyle(stylename);//设置选中的列表样式
         cursor.createList(listfmt);//将列表样式添加到选中文本中
         cursor.endEditBlock();
    }
    else{
        //取消列表样式
        QTextBlockFormat bfmt;//获取当前块格式
        bfmt.setObjectIndex(-1);//移除列表索引
        cursor.mergeBlockFormat(bfmt);//应用新的块格式
    }
    // 必须将修改后的光标设置回文本编辑器
    this->setTextCursor(cursor);
}

void MyChild::closeEvent(QCloseEvent *event)
{
    if(mybesave())
    {
        event->accept();
    }
    else
    {
        event->ignore();
    }

}

bool MyChild::mybesave()
{
    //判断是否修改且保存文档的对话框
    if(!document()->isModified())
        return true;
    QMessageBox::StandardButton ret;
    ret=QMessageBox::warning(this,tr("Qt word"),tr("文件“%1”已经被修改，是否保存").arg(userFriendlyCurrentFile()),QMessageBox::Discard|QMessageBox::Cancel|QMessageBox::Save);


    if(ret==QMessageBox::Save)
    {
        return save();
    }
    else if(ret ==QMessageBox::QMessageBox::Cancel)
    {
        return false;
    }
    return true;
}

void MyChild::setCurrentFile(const QString &filename)//设置最近文件
{
    curFile=QFileInfo(filename).canonicalFilePath();//获取文件路径
    isUntitle=false;//文件不再是未命名状态
    document()->setModified(false);//最近文件没有修改
    setWindowModified(false);//窗口也未修改
    setWindowTitle(userFriendlyCurrentFile()+"[*]");
    //这个方法确保了应用程序内部状态与用户界面始终保持一致，是文档管理功能中的重要组成部分

}
QString MyChild::userFriendlyCurrentFile()
{
    //setCurrentFile 方法的主要作用是更新当前文档的文件信息并重置相关状态，通常在打开现有文件或保存新文件后调用。
    //提取纯文件名：从完整文件路径中提取出不含路径的文件名部分
    return strippedName(curFile);
}
QString MyChild::strippedName(const QString &fullFileName)
{
    //去除路径的文件，，只保留文件名
    return QFileInfo(fullFileName).fileName();//通过路径获取文件名

}

void MyChild::documentWasModified()
{
    // 在设置改变时，设置窗口已修改
    setWindowModified(document()->isModified());
}


